package com.zhanghe.study.thread.pool;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zh
 * @date 2021/12/15 16:11
 */
public class TestExecutorsException {
    public static void main(String[] args) {
//        testFixedThread();
        testMyThread();
    }
    // 测试newFixedThreadPool线程池
    private static void testMyThread() {
        // 创建固定大小的线程池
        ExecutorService pool = new MyThreadPoolExecutor(1);
        for(int i = 0;i<5;i++){
            int finalI = i;

            pool.submit(() ->
            {
                if(finalI == 3){
                    throw new RuntimeException("出错了");
                }
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + ":"+ finalI);
            });
        }
        pool.shutdown();
    }


    // 测试newFixedThreadPool线程池
    private static void testFixedThread() {
        // 创建固定大小的线程池
        ExecutorService pool = Executors.newFixedThreadPool(2,new BizThreadFactory("myThread"));
        for(int i = 0;i<5;i++){
            int finalI = i;

            pool.submit(() ->
            {
                if(finalI == 3){
                    throw new RuntimeException("出错了");
                }
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + ":"+ finalI);
            });
        }
        pool.shutdown();
    }

    // 测试newScheduledThreadPool线程池
    private static void testScheduledThread() {

        ScheduledExecutorService pool = Executors.newScheduledThreadPool(10);
        for(int i = 0;i<5;i++){
            int finalI = i;

            pool.schedule(()->
            {
                if(finalI == 3){
                    throw new RuntimeException("出错了");
                }

                System.out.println(Thread.currentThread().getName() + ":"+ finalI);

            },20, TimeUnit.SECONDS);
        }
        pool.shutdown();
    }

}

class MyThreadPoolExecutor extends ThreadPoolExecutor {

    public MyThreadPoolExecutor(int corePoolSize) {
        this(corePoolSize,corePoolSize,0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
    }
    public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r,t);
        if (t == null && r instanceof Future<?>) {
            try {
                Object result = ((Future<?>) r).get();
            } catch (CancellationException ce) {
                t = ce;
            } catch (ExecutionException ee) {
                t = ee.getCause();
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt(); // ignore/reset
            }
        }
        if(t != null){
            System.out.println("afterExecute获取异常"+t.getMessage());
        }
    }
}

class BizThreadFactory implements ThreadFactory {

    public AtomicInteger threadNumber = new AtomicInteger(1);
    public final String prefixName;

    public BizThreadFactory(String bizName) {
        this.prefixName = "PollName-" + bizName + "-ThreadId-";
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r, prefixName + threadNumber.getAndIncrement());
        t.setUncaughtExceptionHandler(new MyExceptionHandler());

        if (t.isDaemon()) {
            t.setDaemon(false);
        }
        if (t.getPriority() != Thread.NORM_PRIORITY) {
            t.setPriority(Thread.NORM_PRIORITY);
        }
        return t;
    }

    class MyExceptionHandler implements Thread.UncaughtExceptionHandler{

        @Override
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println(t.getName()+"抛出异常"+e.getMessage());
            e.printStackTrace();
        }
    }
}
